﻿#include "ipc.h"
#include "cpsdeocder.h"
#include <QBuffer>
#include <QJsonObject>
#include <QJsonDocument>
#include <QJsonArray>
#include <QFile>
#include <QDir>
#include "commonfuc.h"
#include "logfile.h"
#include <QImage>
#include <QRect>
#include <QPoint>

#define JPGBUFFSIZE 1920*540*3//1920*1080*3/2

void CALLBACK fLoginResultCB(LONG lUserID, DWORD dwResult, LPNET_DVR_DEVICEINFO_V30 lpDeviceInfo , void* pUser)
{
    IPC *tmp = (IPC*)pUser;

    Q_UNUSED(lpDeviceInfo);
    emit tmp->loginOver(lUserID, dwResult, NET_DVR_GetLastError());
}

void CALLBACK fDataCallBack(LONG lRealHandle, DWORD dwDataType, BYTE *pBuffer, DWORD dwBufSize, void* dwUser)
{
    IPC *tmp = (IPC*)dwUser;

    switch (dwDataType)
    {
    case NET_DVR_SYSHEAD:
        break;
    case NET_DVR_STREAMDATA:
        if (dwBufSize > 0)
        {
            QByteArray *m_frame;

            if (lRealHandle == tmp->m_lRealPlayHandle)
            {
                m_frame = &tmp->m_frame_main;
            }
            else if (lRealHandle == tmp->m_lRealPlayHandle1)
            {
                m_frame = &tmp->m_frame_second;
            }
            else
            {
                return ;
            }

            QByteArray frame((const char*)pBuffer, dwBufSize);
            if (frame.size() >= 4 && frame.at(0) == '\0' && frame.at(1) == '\0' && frame.at(2) == '\1' && frame.at(3) == (char)0xba)
            {
                if (m_frame->size() > 0)
                {
                    int totalLen;

                    totalLen = GetH246FromPs(m_frame->data(), m_frame->size());
                    if (totalLen == 0)
                    {
                        *m_frame = frame;
                        return;
                    }
                    *m_frame = m_frame->mid(0, totalLen);

                    if (lRealHandle == tmp->m_lRealPlayHandle)
                    {
                        emit tmp->packetReady(*m_frame);
                    }
                    else if (lRealHandle == tmp->m_lRealPlayHandle1)
                    {
                        emit tmp->packetReady1(*m_frame);
                    }
                }
                m_frame->clear();
            }
            *m_frame += frame;
        }
        break;
    case NET_DVR_STD_VIDEODATA:
        DEBUG_PRINT << dwBufSize;
        break;
    default:
        break;
    }
}

#ifdef NO_WIDGETS
IPC::IPC(QString &proxyId, QString ipcId, STRUCT_IPC_INFO &ipcInfo, STRUCT_RECOG_INFO &faceInfo, STRUCT_RECOG_INFO &plateInfo) :
#else
IPC::IPC(QString &proxyId, QString ipcId, STRUCT_IPC_INFO &ipcInfo, STRUCT_RECOG_INFO &faceInfo, STRUCT_RECOG_INFO &plateInfo, QWidget *widget) :
#endif
    m_id(ipcId),
    m_proxyId(proxyId),
    m_ipcInfo(ipcInfo),
    m_devState(false),
    m_mdStatus(true),
#ifndef NO_WIDGETS
    m_wVideo(widget),
#endif
    m_lUserID(-1),
    m_lRealPlayHandle(-1),
    m_lRealPlayHandle1(-1),
    m_lAlarmChanHandle(-1),
	m_cfg(),
    m_faceInfo(faceInfo),
    m_plateInfo(plateInfo),
    m_sms0(Q_NULLPTR),
    m_sms1(Q_NULLPTR),
    m_eventLoop(Q_NULLPTR),
    m_lastMotionTime(0),
    m_lastCarTime(0),
    m_lastFaceTime(0),
    m_lastStrangerTime(0),
	m_snapTimer(),
	m_openList()
{
    connect(this, SIGNAL(loginOver(long,long,long)), this, SLOT(onLoginOver(long,long,long)));
    connect(this, SIGNAL(motionAlarm()), this, SLOT(onMotionAlarm()));
	connect(this, SIGNAL(sigSnapAndGetVideo(QByteArray)), this, SLOT(onSnapAndGetVideo(QByteArray)));
	connect(&m_snapTimer, SIGNAL(timeout()), this, SLOT(onSnapTimeout()));
    this->start();
}

IPC::~IPC()
{
    if (m_eventLoop != Q_NULLPTR)
    {
        m_eventLoop->exit();
    }

    if (m_sms0 != Q_NULLPTR)
    {
        delete m_sms0;
    }
    if (m_sms1 != Q_NULLPTR)
    {
        delete m_sms1;
    }

    devAntiInit();
	m_openList.clear();

    this->quit();
    this->wait();
}

void IPC::devInit()
{
    DEBUG_PRINT << m_ipcInfo.ip;
    // 注册IPC设备，异步登录
    NET_DVR_USER_LOGIN_INFO loginInfo;
    memset(&loginInfo, 0, sizeof(loginInfo));
    strcpy(loginInfo.sDeviceAddress, m_ipcInfo.ip.toLatin1().data());
    loginInfo.wPort = m_ipcInfo.port;
    strcpy(loginInfo.sUserName, m_ipcInfo.username.toLatin1().data());
    strcpy(loginInfo.sPassword, m_ipcInfo.password.toLatin1().data());
    loginInfo.cbLoginResult = fLoginResultCB;
    loginInfo.pUser = (void *)this;
    loginInfo.bUseAsynLogin = true;

    NET_DVR_DEVICEINFO_V40 struDeviceInfoV40;
    memset(&struDeviceInfoV40, 0, sizeof(struDeviceInfoV40));

    NET_DVR_Login_V40(&loginInfo, &struDeviceInfoV40);
}

void IPC::devAntiInit()
{
    DEBUG_PRINT << m_ipcInfo.ip;
    //注销设备
    if (m_lUserID >= 0)
    {
        if (m_lAlarmChanHandle >= 0 && !NET_DVR_CloseAlarmChan_V30(m_lAlarmChanHandle))
        {
            WARNING_PRINT << m_ipcInfo.ip << "NET_DVR_CloseAlarmChan_V30 error:" << NET_DVR_GetLastError();
        }
        else
        {
            m_lAlarmChanHandle = -1;
        }

        if (m_lRealPlayHandle >= 0 && !NET_DVR_StopRealPlay(m_lRealPlayHandle))
        {
            WARNING_PRINT << m_ipcInfo.ip << "NET_DVR_StopRealPlay main error:" << NET_DVR_GetLastError();
        }
        else
        {
            m_lRealPlayHandle = -1;
        }

        if (m_lRealPlayHandle1 >= 0 && !NET_DVR_StopRealPlay(m_lRealPlayHandle1))
        {
            WARNING_PRINT << m_ipcInfo.ip << "NET_DVR_StopRealPlay sub error:" << NET_DVR_GetLastError();
        }
        else
        {
            m_lRealPlayHandle1 = -1;
        }

        if (!NET_DVR_Logout(m_lUserID))
        {
            WARNING_PRINT << m_ipcInfo.ip << "NET_DVR_Logout error:" << NET_DVR_GetLastError();
        }
        else
        {
            m_lUserID = -1;
        }
    }
}

void IPC::run()
{
    QTimer timer;
    m_eventLoop = new QEventLoop();
    m_face = new Recognize(m_proxyId, m_faceInfo);
    m_plate = new Recognize(m_proxyId, m_plateInfo);
    connect(m_face, SIGNAL(postOver(QByteArray, QByteArray)), this, SLOT(onFacePostOver(QByteArray, QByteArray)));
    connect(m_plate, SIGNAL(postOver(QByteArray,QByteArray)), this, SLOT(onPlatePostOver(QByteArray,QByteArray)));
    connect(&timer, SIGNAL(timeout()), this, SLOT(onTimeout()), Qt::DirectConnection);
    timer.start(100);
    m_eventLoop->exec();
    delete m_plate;
    delete m_face;
    delete m_eventLoop;
    m_eventLoop = Q_NULLPTR;
}

void IPC::onLoginOver(long lUserID, long dwResult, long err)
{
    if (dwResult == 1)
    {
        m_lUserID = lUserID;
        DEBUG_PRINT << m_ipcInfo.ip << "";

        //启动预览并设置回调数据流
        NET_DVR_PREVIEWINFO struPlayInfo;
        memset(&struPlayInfo, 0, sizeof(struPlayInfo));
        struPlayInfo.hPlayWnd = 0; //(HWND)m_wVideo->winId(); //需要SDK 解码时句柄设为有效值，仅取流不解码时可设为空
        struPlayInfo.lChannel = 1; //预览通道号
        struPlayInfo.dwStreamType = 0; //0-主码流，1-子码流，2-码流3，3-码流4，以此类推
        struPlayInfo.dwLinkMode = 0; //0- TCP 方式，1- UDP 方式，2- 多播方式，3- RTP 方式，4-RTP/RTSP，5-RSTP/HTTP
        struPlayInfo.bBlocked = 1; //0- 非阻塞取流，1- 阻塞取流
        m_lRealPlayHandle = NET_DVR_RealPlay_V40(m_lUserID, &struPlayInfo, fDataCallBack, this);

        memset(&struPlayInfo, 0, sizeof(struPlayInfo));
        struPlayInfo.hPlayWnd = (HWND)0; //需要SDK 解码时句柄设为有效值，仅取流不解码时可设为空
        struPlayInfo.lChannel = 1; //预览通道号
        struPlayInfo.dwStreamType = 1; //0-主码流，1-子码流，2-码流3，3-码流4，以此类推
        struPlayInfo.dwLinkMode = 0; //0- TCP 方式，1- UDP 方式，2- 多播方式，3- RTP 方式，4-RTP/RTSP，5-RSTP/HTTP
        struPlayInfo.bBlocked = 1; //0- 非阻塞取流，1- 阻塞取流
        m_lRealPlayHandle1 = NET_DVR_RealPlay_V40(m_lUserID, &struPlayInfo, fDataCallBack, this);

        //配置移动侦测
        NET_DVR_PICCFG_V40 struParams;
        memset(&struParams, 0, sizeof(struParams));
        BOOL bRet;
        DWORD dwReturnLen;
        bRet = NET_DVR_GetDVRConfig(m_lUserID, NET_DVR_GET_PICCFG_V40, 1, &struParams, sizeof(NET_DVR_PICCFG_V40), &dwReturnLen);
        if (!bRet)
        {
            WARNING_PRINT << m_ipcInfo.ip << "NET_DVR_PICCFG_V40 error:" << NET_DVR_GetLastError();
        }
        //struParams.dwShowChanName = 0;
        //struParams.dwShowOsd = 0;
        struParams.struMotion.byEnableHandleMotion = 1;
        struParams.struMotion.byEnableDisplay = 0;
        struParams.struMotion.byConfigurationMode = 0;
        memset(struParams.struMotion.struMotionMode.struMotionSingleArea.byMotionScope, 0 ,
               sizeof(struParams.struMotion.struMotionMode.struMotionSingleArea.byMotionScope));
        for (int i = m_ipcInfo.motionStartY; i < (m_ipcInfo.motionStartY + m_ipcInfo.motionHeight); i++)
        {
            for (int j = m_ipcInfo.motionStartX; j < (m_ipcInfo.motionStartX + m_ipcInfo.motionWidth); j++)
            {
                struParams.struMotion.struMotionMode.struMotionSingleArea.byMotionScope[i][j] = 1;
            }
        }
        struParams.struMotion.struMotionMode.struMotionSingleArea.byMotionSensitive = m_ipcInfo.motionSensitive;
        struParams.struMotion.dwHandleType |= 0x04;
        bRet = NET_DVR_SetDVRConfig(m_lUserID, NET_DVR_SET_PICCFG_V40, 1, &struParams, sizeof(NET_DVR_PICCFG_V40));
        if (!bRet)
        {
            WARNING_PRINT << m_ipcInfo.ip << "NET_DVR_SET_PICCFG_V40 error:" << NET_DVR_GetLastError();
            m_mdStatus = false;
        }

        //启用布防
        NET_DVR_SETUPALARM_PARAM struAlarmParam;
        memset(&struAlarmParam, 0, sizeof(struAlarmParam));
        struAlarmParam.dwSize = sizeof(struAlarmParam);
        struAlarmParam.byAlarmInfoType = 0;
        m_lAlarmChanHandle = NET_DVR_SetupAlarmChan_V41(m_lUserID, &struAlarmParam);

        m_devState = true;
        DEBUG_PRINT << m_ipcInfo.ip << "success";
        if(!m_cfg.m_cfg.bUseNvr)
            m_snapTimer.start();
    }
    else
    {
        ERROR_PRINT << m_ipcInfo.ip << "NET_DVR_Login_V40 error:" << err;
        if (err != 1)
        {
            m_lUserID = -1;
        }
        else
        {
            ERROR_PRINT << m_ipcInfo.ip << "wrong username or password ";
        }
    }
}

void IPC::onMotionAlarm()
{
    m_lastMotionTime = time(Q_NULLPTR);
}

void IPC::onTimeout()
{
    if (m_lUserID >= 0 && m_lRealPlayHandle >= 0 && m_devState &&
            (!m_mdStatus || time(Q_NULLPTR) - m_lastMotionTime <= 5) &&
            (((m_ipcInfo.type & 1 << IPC_TYPE_FACE) && m_face->m_state) ||
             ((m_ipcInfo.type & 1 << IPC_TYPE_PLATE) && m_plate->m_state)))
    {
        QByteArray jpg;
        DWORD buffLen;

        jpg.resize(1920*1080*3/2);

        NET_DVR_JPEGPARA jpegPara;
        jpegPara.wPicSize = 0xff;
        jpegPara.wPicQuality = 1;
        if (FALSE == NET_DVR_CaptureJPEGPicture_NEW(m_lUserID, 1, &jpegPara, jpg.data(), jpg.size(), &buffLen))
        {
            DEBUG_PRINT << "NET_DVR_CaptureJPEGPicture_NEW" << NET_DVR_GetLastError();
            return;
        }

        if (buffLen > 0 && (int)buffLen < jpg.size())
        {
#if 0
            QByteArray jpgFull;
            QByteArray jpgClip;
            QBuffer jpgFullBuf(&jpgFull);
            QBuffer jpgClipBuf(&jpgClip);
            QImage img;

            img.loadFromData((unsigned char*)jpg.data(), buffLen);
            int x = (m_ipcInfo.motionStartX - m_ipcInfo.recognitionFrame) * (img.width() / 22);
            int y = (m_ipcInfo.motionStartY - m_ipcInfo.recognitionFrame) * (img.height() / 18);
            int width = (m_ipcInfo.motionWidth + 2 * m_ipcInfo.recognitionFrame) * (img.width() / 22);
            int height = (m_ipcInfo.motionHeight + 2 * m_ipcInfo.recognitionFrame) * (img.height() / 18);

            img.save(&jpgFullBuf, "JPG");
            if ((m_ipcInfo.type & (1 << IPC_TYPE_FACE)) != 0 && time(Q_NULLPTR) - m_lastFaceTime > m_faceInfo.successGap)
            {
                img.copy(x, y, width, height)/*.scaled(m_faceInfo.postWidth, m_faceInfo.postHeight)*/.save(&jpgClipBuf, "JPG", m_ipcInfo.picQuality);
                QFile file("test_face.jpg");
                if (file.open(QIODevice::ReadOnly))
                {
                    jpgClip = file.readAll();
                    file.close();
                }
                m_face->recognize(jpgClip);
            }
            if ((m_ipcInfo.type & (1 << IPC_TYPE_PLATE)) != 0 && time(Q_NULLPTR) - m_lastCarTime > m_plateInfo.successGap)
            {
                img.copy(x, y, width, height).scaled(m_plateInfo.postWidth, m_plateInfo.postHeight).save(&jpgClipBuf, "JPG", m_ipcInfo.picQuality);
                QFile file("test_plate.jpg");
                if (file.open(QIODevice::ReadOnly))
                {
                    jpgClip = file.readAll();
                    file.close();
                }
                m_plate->recognize(jpgClip);
            }
#else
            jpg = jpg.mid(0, buffLen);
            if ((m_ipcInfo.type & (1 << IPC_TYPE_FACE)) != 0 && time(Q_NULLPTR) - m_lastFaceTime > m_faceInfo.successGap)
            {
                QFile file("test_face.jpg");
                if (file.open(QIODevice::ReadOnly))
                {
                    jpg = file.readAll();
                    file.close();
                }
                m_face->recognize(jpg);
            }
            if ((m_ipcInfo.type & (1 << IPC_TYPE_PLATE)) != 0 && time(Q_NULLPTR) - m_lastCarTime > m_plateInfo.successGap)
            {
                QFile file("test_plate.jpg");
                if (file.open(QIODevice::ReadOnly))
                {
                    jpg = file.readAll();
                    file.close();
                }
                m_plate->recognize(jpg);
            }
#endif
        }
    }
    else if (m_lUserID == -1)
    {
        m_lUserID = -2;
        this->devInit();
    }
}

void IPC::onFacePostOver(const QByteArray &jpg, const QByteArray &data)
{
    QJsonParseError jsonErr;
    QJsonObject jsonObj;
    QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &jsonErr);

    if (jsonErr.error != QJsonParseError::NoError && !jsonDoc.isObject())
    {
        WARNING_PRINT << "recv unkown msg" << data << jsonErr.error;
        return ;
    }

    jsonObj = jsonDoc.object();

    if (jsonObj["is_alarm"].toInt() != 0 && jsonObj["is_alarm"].toInt() != 1 && jsonObj["is_alarm"].toInt() != 2)
    {
        return;
    }

    QJsonObject jsonSnd;

    jsonSnd["estate_id"] = QString("").sprintf("%d", m_proxyId.toInt());
    jsonSnd["device_id"] = m_proxyId + "_" + m_id;
    jsonSnd["function_name"] = "face";
    jsonSnd["create_time"] = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
    jsonSnd["pic_snap_origin"] = QString(QCryptographicHash::hash(jpg, QCryptographicHash::Md5).toHex());
    jsonSnd["is_alarm"] = (jsonObj["is_alarm"].toInt() == 1) ? "true" : "false";
    jsonSnd["event_type"] = "people";

    if (m_ipcInfo.intercomMac.size() > 0 && jsonObj["is_alarm"].toInt() == 0)
    {
        jsonSnd["openType"] = 3;
        jsonSnd["openTime"] = QDateTime::currentDateTime().toString("yyMMddhhmmss");
        jsonSnd["doorInfo"] = m_ipcInfo.doorInfo;
        jsonSnd["userId"] = jsonObj["result"].toArray().at(0).toObject()["detect_name"];
		emit faceSuccess(m_ipcInfo.intercomMac, jsonSnd["userId"].toString());
    }

    QImage img;
    img.loadFromData(jpg);
    if (jsonObj["is_alarm"].toInt() != 2)
    {
        m_lastFaceTime = time(Q_NULLPTR);

        for (int i = jsonObj["result"].toArray().size() - 1; i >= 0; i--)
        {
            QJsonObject jsonSnap;
            QJsonArray snapArray;
            QByteArray jpgFace;
            QBuffer jpgBuf(&jpgFace);
            int x0 = jsonObj["result"].toArray().at(i).toObject()["crop"].toArray().at(0).toString().toInt();
            int y0 = jsonObj["result"].toArray().at(i).toObject()["crop"].toArray().at(1).toString().toInt();
            int x1 = jsonObj["result"].toArray().at(i).toObject()["crop"].toArray().at(2).toString().toInt();
            int y1 = jsonObj["result"].toArray().at(i).toObject()["crop"].toArray().at(3).toString().toInt();

            img.copy(QRect(QPoint(x0, y0), QPoint(x1, y1))).save(&jpgBuf, "JPG");
            jsonSnap["pic"] = QString(QCryptographicHash::hash(jpgFace, QCryptographicHash::Md5).toHex());
            jsonSnap["create_time"] = QTime::currentTime().toString("hh:mm:ss");
            snapArray.append(jsonSnap);
            jsonSnd["pic_snap_list"] = snapArray;
            jsonSnd["similar"] = jsonObj["result"].toArray().at(i).toObject()["match_degree"];
            jsonSnd["item_id"] = jsonObj["result"].toArray().at(i).toObject()["detect_name"];
            jsonSnd["pic_input_origin"] = jsonObj["result"].toArray().at(i).toObject()["db_md5"];

            emit postReport(QJsonDocument(jsonSnd).toJson(QJsonDocument::Compact));
            emit postPic(jpgFace);
        }
    }
    else if (time(Q_NULLPTR) - m_lastStrangerTime < m_faceInfo.failedGap)
    {
        return;
    }
    else
    {
        QJsonObject jsonSnap;
        QJsonArray snapArray;
        QByteArray jpgFace;
        QBuffer jpgBuf(&jpgFace);
        int x0 = jsonObj["result"].toArray().at(0).toObject()["crop"].toArray().at(0).toString().toInt();
        int y0 = jsonObj["result"].toArray().at(0).toObject()["crop"].toArray().at(1).toString().toInt();
        int x1 = jsonObj["result"].toArray().at(0).toObject()["crop"].toArray().at(2).toString().toInt();
        int y1 = jsonObj["result"].toArray().at(0).toObject()["crop"].toArray().at(3).toString().toInt();

        img.copy(QRect(QPoint(x0, y0), QPoint(x1, y1))).save(&jpgBuf, "JPG");
        jsonSnap["pic"] = QString(QCryptographicHash::hash(jpgFace, QCryptographicHash::Md5).toHex());
        jsonSnap["create_time"] = QTime::currentTime().toString("hh:mm:ss");
        snapArray.append(jsonSnap);
        jsonSnd["pic_snap_list"] = snapArray;
        jsonSnd["item_id"] = "";
        jsonSnd["pic_input_origin"] = "";

        int degree = jsonObj["result"].toArray().at(0).toObject()["match_degree_black"].toInt();
        int degree_white = jsonObj["result"].toArray().at(0).toObject()["match_degree_white"].toInt();
        if (degree_white > degree)
        {
            degree = degree_white;
        }
        jsonSnd["similar"] = degree;

        emit postReport(QJsonDocument(jsonSnd).toJson(QJsonDocument::Compact));
        emit postPic(jpgFace);
    }

    m_lastStrangerTime = time(Q_NULLPTR);
    emit postBigData(QJsonDocument(jsonSnd).toJson(QJsonDocument::Compact));
    emit postPic(jpg);
}

void IPC::onPlatePostOver(const QByteArray &jpg, const QByteArray &data)
{
    QString log;
    QJsonParseError jsonErr;
    QJsonObject jsonObj;
    QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &jsonErr);

    if (jsonErr.error != QJsonParseError::NoError && !jsonDoc.isObject())
    {
        log.clear();
        log.sprintf("recv unkown msg: %s, %d", data.toStdString().c_str(), jsonErr.error);
        logFile::printLog(log);
        WARNING_PRINT << "recv unkown msg" << data << jsonErr.error;
        return ;
    }

    jsonObj = jsonDoc.object();

    if (!jsonObj["result"].toBool())
    {
        return ;
    }

    m_lastCarTime = time(Q_NULLPTR);

    QJsonObject jsonSnd;

    jsonSnd["estate_id"] = QString("").sprintf("%d", m_proxyId.toInt());
    jsonSnd["device_id"] = m_proxyId + "_" + m_id;
    jsonSnd["function_name"] = "car";
    jsonSnd["create_time"] = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
    jsonSnd["pic_snap_origin"] = QString(QCryptographicHash::hash(jpg, QCryptographicHash::Md5).toHex());
    jsonSnd["car_plate_number"] = jsonObj["car_plate"];
    jsonSnd["car_color"] = jsonObj["car_color"];
    jsonSnd["car_model"] = jsonObj["car_model"];
    jsonSnd["similar"] = jsonObj["plate_score"];

    emit postReport(QJsonDocument(jsonSnd).toJson(QJsonDocument::Compact));
    emit postBigData(QJsonDocument(jsonSnd).toJson(QJsonDocument::Compact));
    emit postPic(jpg);
}

void IPC::startSMS(QString ip, int port, QString code)
{
    QString log;
    int index = code.indexOf('&') - 1;

    if (index < 0)
    {
        log.clear();
        log.sprintf("startSMS code =  %s, returned!", code.toStdString().c_str());
        logFile::printLog(log);
        WARNING_PRINT << code;
        return;
    }
    switch (code.at(index).toLatin1())
    {
    case '0':
        if (m_sms0 == Q_NULLPTR)
        {
            m_sms0 = new SMS(ip, port, code);
            connect(&this->m_sms0->m_fd, SIGNAL(disconnected()), this, SLOT(stopSMS0()));
            connect(this, SIGNAL(packetReady(QByteArray)), this->m_sms0, SLOT(writeFrame(QByteArray)));
        }
        break;
    case '1':
        if (m_sms1 == Q_NULLPTR)
        {
            m_sms1 = new SMS(ip, port, code);
            connect(&this->m_sms1->m_fd, SIGNAL(disconnected()), this, SLOT(stopSMS1()));
            connect(this, SIGNAL(packetReady1(QByteArray)), this->m_sms1, SLOT(writeFrame(QByteArray)));
        }
        break;
    default:
        WARNING_PRINT << code << code.at(index);
        break;
    }
}

void IPC::stopSMS0()
{
    disconnect(this, SIGNAL(packetReady(QByteArray)), this->m_sms0, SLOT(writeFrame(QByteArray)));
    m_sms0->deleteLater();
    m_sms0 = Q_NULLPTR;
}

void IPC::stopSMS1()
{
    disconnect(this, SIGNAL(packetReady1(QByteArray)), this->m_sms1, SLOT(writeFrame(QByteArray)));
    m_sms1->deleteLater();
    m_sms1 = Q_NULLPTR;
}

//##########################################抓拍相关############################################//
void IPC::onSnapTimeout()
{
    downLoadVideo();
}

void IPC::onSnapAndGetVideo(QByteArray data)
{
    QString strLog;
    DEBUG_PRINT << m_ipcInfo.ip << " opendoor come in";
    strLog.clear();
    strLog.sprintf("%s opendoor come in",m_ipcInfo.ip.toStdString().c_str());
    logFile::printLog(strLog);

    if((m_openList.size()>1000)||(m_lUserID<0))
    {
        WARNING_PRINT << "too many SnapAndGetVideo had not deal or ipc had not login,m_openList.size=" << m_openList.size() << ",m_lUserID=" << m_lUserID;
        strLog.clear();
        strLog.sprintf("too many SnapAndGetVideo had not deal or ipc had not login,m_openList.size=%d,m_lUserID=%ld",m_openList.size(),m_lUserID);
        logFile::printLog(strLog);
        emit snapAndGetVideoOK(data,NULL,NULL,NULL,NULL);
        return;
    }

    STRUCT_SNAP snapAndVideo;
    snapAndVideo.data=data;
    snapAndVideo.stime=time(NULL);

    memset(snapAndVideo.jpg1,0,sizeof(snapAndVideo.jpg1));
    memset(snapAndVideo.jpg2,0,sizeof(snapAndVideo.jpg2));
    memset(snapAndVideo.jpg3,0,sizeof(snapAndVideo.jpg3));

    m_openList.append(snapAndVideo);
}

int IPC::downLoadVideo()
{
    QString strLog;
    time_t currTime=time(NULL);
    int diffTime;
    time_t endT;
    int i;
    int index;

    if(m_openList.size()<=0)
        return 0;

    for(i=0;i<m_openList.size();)
    {
    diffTime=currTime-m_openList[i].stime;
    index=0;
    if(3==m_openList[i].jpgStep)//如果已经抓拍了三张，则继续下一个
        goto GETVIDEO;
    if(m_lUserID>=0)
    {
        switch (m_openList[i].jpgStep) {
        case 0:
            index=1;
            break;
        case 1:
            if(diffTime>=2)
                index=2;
//            else
//                index=-1;//list按时间排序，所以这次该列表时间没到下面的列表就不用看了,取图片间隔为1s的时候用
            break;
        case 2:
            if(diffTime>=4)
                index=3;
            break;
        default:
            index=0;
            break;
        }

        if(-1==index)//推出for循环
            return 0;
        if(0!=index)//还要抓拍
        {
            QByteArray jpg;
            unsigned long buffLen;
            bool ret=false;
            jpg.resize(JPGBUFFSIZE);

            NET_DVR_JPEGPARA jpegPara;
            jpegPara.wPicSize=0xff;
            jpegPara.wPicQuality=1;

#ifndef WIN32
            ret=NET_DVR_CaptureJPEGPicture_NEW(m_lUserID,1,&jpegPara,jpg.data(),jpg.size(),(LPDWORD)&buffLen);
#else
            ret=NET_DVR_CaptureJPEGPicture_NEW(m_lUserID,1,&jpegPara,jpg.data(),jpg.size(),(unsigned long*)&buffLen);
#endif

            m_openList[i].snapTime++;
            if(ret&&(buffLen > 0) &&((int)buffLen < jpg.size()))
            {
                QString temp;

                QString strRoot = CommonFuc::getAppDirPath();
                temp.append(strRoot);
                temp.append("record/");
                QDir nvrDir;
                if (!nvrDir.exists(temp))
                {
                    nvrDir.mkdir(temp);
                }

                temp.append(QDateTime::currentDateTime().toString("yyyy-MM-dd_hh_mm_ss_zzz_"));
                temp.append(QString::number(index));//test
                temp.append(".jpg");
                QImage img;
                img.loadFromData((unsigned char*)jpg.data(), buffLen);
                img.save(temp,"JPG");

                switch (index) {
                case 1:
                    strcpy(m_openList[i].jpg1,temp.toStdString().data());
                    break;
                case 2:
                    strcpy(m_openList[i].jpg2,temp.toStdString().data());
                    break;
                case 3:
                    strcpy(m_openList[i].jpg3,temp.toStdString().data());
                    break;
                default:
                    break;
                }
                m_openList[i].jpgStep=index;
            }
        }
    }
    else
    {
        WARNING_PRINT << m_ipcInfo.ip << " get pic fail";
        strLog.clear();
        strLog.sprintf("%s get pic fail",m_ipcInfo.ip.toStdString().c_str());
        logFile::printLog(strLog);
        m_openList[i].jpgStep=3;
    }
GETVIDEO:
    endT=m_openList[i].stime;
    if((currTime>endT+180)||(m_openList[i].snapTime>30))// 大于结束时间3min或者抓拍次数大于30次
    {
        WARNING_PRINT << m_ipcInfo.ip << " get pic and video outtime";
        strLog.clear();
        strLog.sprintf("%s get pic and video outtime",m_ipcInfo.ip.toStdString().c_str());
        logFile::printLog(strLog);
        m_openList[i].jpgStep=3;
    }

   if((3==m_openList[i].jpgStep)&&(!m_openList[i].hadSend))//已录制完毕但未发送
   {
       QString jpg1,jpg2,jpg3;
       jpg1.append(m_openList[i].jpg1);
       jpg2.append(m_openList[i].jpg2);
       jpg3.append(m_openList[i].jpg3);
       emit snapAndGetVideoOK(m_openList[i].data, jpg1, jpg2, jpg3, "");
       m_openList[i].hadSend=true;
       DEBUG_PRINT << m_ipcInfo.ip << " jpg1=" << jpg1 <<  " jpg2=" << jpg2 <<" jpg3=" << jpg3;
       strLog.clear();
       strLog.sprintf("%s jpg1=%s,jpg2=%s,jpg3=%s",m_ipcInfo.ip.toStdString().c_str(),jpg1.toStdString().c_str(),jpg2.toStdString().c_str(),jpg3.toStdString().c_str());
       logFile::printLog(strLog);
       m_openList.removeAt(i);
   }
   else
   {
       i++;
   }
   }
   return 0;
}
